package com.lxk.mall.pms.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.lxk.mall.pms.controller.app.vo.AppCommentPageReqVO;
import com.lxk.mall.pms.domain.PmsProductComment;
import com.lxk.mall.pms.domain.PmsProductSku;
import com.lxk.mall.pms.domain.PmsProductSpu;
import com.lxk.mall.pms.domain.bo.comment.PmsProductCommentBo;
import com.lxk.mall.pms.domain.bo.comment.ProductCommentReplyReqBO;
import com.lxk.mall.pms.domain.bo.comment.ProductCommentUpdateVisibleReqBO;
import com.lxk.mall.pms.enums.PmsErrorCodeConstants;
import com.lxk.mall.pms.mapper.PmsProductCommentMapper;
import com.lxk.mall.pms.service.IPmsProductCommentService;
import com.lxk.mall.pms.service.IPmsProductSkuService;
import com.lxk.mall.pms.service.IPmsProductSpuService;
import jakarta.annotation.Resource;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.lxk.mall.pms.domain.vo.comment.PmsProductCommentVo;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.Collection;

import static com.lxk.mall.pms.enums.PmsErrorCodeConstants.COMMENT_NOT_EXISTS;

/**
 * 商品评论Service业务层处理
 *
 * @author Lion Li
 * @date 2024-06-06
 */
@RequiredArgsConstructor
@Service
public class PmsProductCommentServiceImpl implements IPmsProductCommentService {

    private final PmsProductCommentMapper baseMapper;

    @Resource
    private IPmsProductSpuService productSpuService;

    @Resource
    @Lazy
    private IPmsProductSkuService productSkuService;


    /**
     * 查询商品评论
     *
     * @param id 主键
     * @return 商品评论
     */
    @Override
    public PmsProductCommentVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询商品评论列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 商品评论分页列表
     */
    @Override
    public TableDataInfo<PmsProductCommentVo> queryPageList(PmsProductCommentBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<PmsProductComment> lqw = buildQueryWrapper(bo);
        lqw.orderByDesc(PmsProductComment::getCreateTime);
        Page<PmsProductCommentVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的商品评论列表
     *
     * @param bo 查询条件
     * @return 商品评论列表
     */
    @Override
    public List<PmsProductCommentVo> queryList(PmsProductCommentBo bo) {
        LambdaQueryWrapper<PmsProductComment> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<PmsProductComment> buildQueryWrapper(PmsProductCommentBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<PmsProductComment> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getUserId() != null, PmsProductComment::getUserId, bo.getUserId());
        lqw.like(StringUtils.isNotBlank(bo.getUserNickname()), PmsProductComment::getUserNickname, bo.getUserNickname());
        lqw.eq(StringUtils.isNotBlank(bo.getUserAvatar()), PmsProductComment::getUserAvatar, bo.getUserAvatar());
        lqw.eq(bo.getAnonymous() != null, PmsProductComment::getAnonymous, bo.getAnonymous());
        lqw.eq(bo.getOrderId() != null, PmsProductComment::getOrderId, bo.getOrderId());
        lqw.eq(bo.getOrderItemId() != null, PmsProductComment::getOrderItemId, bo.getOrderItemId());
        lqw.eq(bo.getSpuId() != null, PmsProductComment::getSpuId, bo.getSpuId());
        lqw.like(StringUtils.isNotBlank(bo.getSpuName()), PmsProductComment::getSpuName, bo.getSpuName());
        lqw.eq(bo.getSkuId() != null, PmsProductComment::getSkuId, bo.getSkuId());
        lqw.eq(StringUtils.isNotBlank(bo.getSkuPicUrl()), PmsProductComment::getSkuPicUrl, bo.getSkuPicUrl());
        lqw.eq(StringUtils.isNotBlank(bo.getSkuProperties()), PmsProductComment::getSkuProperties, bo.getSkuProperties());
        lqw.eq(bo.getVisible() != null, PmsProductComment::getVisible, bo.getVisible());
        lqw.eq(bo.getScores() != null, PmsProductComment::getScores, bo.getScores());
        lqw.eq(bo.getDescriptionScores() != null, PmsProductComment::getDescriptionScores, bo.getDescriptionScores());
        lqw.eq(bo.getBenefitScores() != null, PmsProductComment::getBenefitScores, bo.getBenefitScores());
        lqw.eq(StringUtils.isNotBlank(bo.getContent()), PmsProductComment::getContent, bo.getContent());
        lqw.eq(StringUtils.isNotBlank(bo.getPicUrls()), PmsProductComment::getPicUrls, bo.getPicUrls());
        lqw.eq(bo.getReplyStatus() != null, PmsProductComment::getReplyStatus, bo.getReplyStatus());
        lqw.eq(bo.getReplyUserId() != null, PmsProductComment::getReplyUserId, bo.getReplyUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getReplyContent()), PmsProductComment::getReplyContent, bo.getReplyContent());
        lqw.eq(bo.getReplyTime() != null, PmsProductComment::getReplyTime, bo.getReplyTime());
        return lqw;
    }

    /**
     * 新增虚拟评论。admin端使用
     *
     * @param bo 商品评论
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(PmsProductCommentBo bo) {
        PmsProductComment add = MapstructUtils.convert(bo, PmsProductComment.class);
        // 校验 SKU
        PmsProductSku sku = validateSku(add.getSkuId());
        // 校验 SPU
        PmsProductSpu spu = validateSpu(sku.getSpuId());
        addField(add, spu, sku);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    private void addField(PmsProductComment comment, PmsProductSpu spu, PmsProductSku sku) {
        comment.setScores(this.convertScores(comment.getDescriptionScores(), comment.getBenefitScores()));

        comment.setVisible(true);
        comment.setUserId(0L);
        comment.setAnonymous(false);
        if (spu != null) {
            comment.setSpuId(spu.getId());
            comment.setSpuName(spu.getName());
        }
        if (sku != null) {
            comment.setSkuPicUrl(sku.getPicUrl());
            comment.setSkuProperties(sku.getProperties());
        }
    }

    private PmsProductSku validateSku(Long skuId) {
        PmsProductSku sku = productSkuService.getSku(skuId);
        if (sku == null) {
            throw new ServiceException(PmsErrorCodeConstants.SKU_NOT_EXISTS);
        }
        return sku;
    }

    private PmsProductSpu validateSpu(Long spuId) {
        PmsProductSpu spu = productSpuService.getSpu(spuId);
        if (null == spu) {
            throw new ServiceException(PmsErrorCodeConstants.SPU_NOT_EXISTS);
        }
        return spu;
    }

    /**
     * 修改商品评论
     *
     * @param bo 商品评论
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(PmsProductCommentBo bo) {
        PmsProductComment update = MapstructUtils.convert(bo, PmsProductComment.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(PmsProductComment entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除商品评论信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public void replyComment(ProductCommentReplyReqBO replyVO, Long userId) {
        // 校验评论是否存在
        validateCommentExists(replyVO.getId());
        // 回复评论
        PmsProductComment comment = new PmsProductComment();
        comment.setId(replyVO.getId());
        comment.setReplyTime(DateUtil.date());
        comment.setReplyUserId(userId);
        comment.setReplyStatus(Boolean.TRUE);
        comment.setReplyContent(replyVO.getReplyContent());
        baseMapper.updateById(comment);
    }

    @Override
    public void updateCommentVisible(ProductCommentUpdateVisibleReqBO updateReqVO) {
        // 校验评论是否存在
        validateCommentExists(updateReqVO.getId());

        PmsProductComment comment = new PmsProductComment();
        comment.setId(updateReqVO.getId());
        comment.setVisible(updateReqVO.getVisible());
        // 更新可见状态
        baseMapper.updateById(comment);
    }

    @Override
    public TableDataInfo<PmsProductComment> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) {
        LambdaQueryWrapper<PmsProductComment> lqw = new LambdaQueryWrapper<PmsProductComment>();
        if (pageVO.getSpuId() != null) {
            lqw.eq(PmsProductComment::getSpuId, pageVO.getSpuId());
        }
        if (visible != null) {
            lqw.eq(PmsProductComment::getVisible, visible);
        }
        // 构建评价查询语句
        appendTabQuery(lqw, pageVO.getType());
        // 按评价时间排序最新的显示在前面
        lqw.orderByDesc(PmsProductComment::getCreateTime);
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageSize(pageVO.getPageSize());
        pageQuery.setPageNum(pageVO.getPageNo());
        Page<PmsProductComment> page = baseMapper.selectPage(pageQuery.build(), lqw);
        return TableDataInfo.build(page);
    }

    private PmsProductComment validateCommentExists(Long id) {
        PmsProductComment productComment = baseMapper.selectById(id);
        if (productComment == null) {
            throw new ServiceException(COMMENT_NOT_EXISTS);
        }
        return productComment;
    }

    static void appendTabQuery(LambdaQueryWrapper<PmsProductComment> lqw, Integer type) {
        // 构建好评查询语句：好评计算 总评 >= 4
        if (ObjectUtil.equal(type, AppCommentPageReqVO.GOOD_COMMENT)) {
            lqw.ge(PmsProductComment::getScores, 4);
        }
        // 构建中评查询语句：中评计算 总评 >= 3 且 总评 < 4
        if (ObjectUtil.equal(type, AppCommentPageReqVO.MEDIOCRE_COMMENT)) {
            lqw.ge(PmsProductComment::getScores, 3);
            lqw.lt(PmsProductComment::getScores, 4);
        }
        // 构建差评查询语句：差评计算 总评 < 3
        if (ObjectUtil.equal(type, AppCommentPageReqVO.NEGATIVE_COMMENT)) {
            lqw.lt(PmsProductComment::getScores, 3);
        }
    }

    /**
     * 计算评价最终综合评分 最终星数 = （商品评星 + 服务评星） / 2
     *
     * @param descriptionScores
     * @param benefitScores
     * @return
     */
    Integer convertScores(Integer descriptionScores, Integer benefitScores) {
        BigDecimal sumScore = new BigDecimal(descriptionScores + benefitScores);
        BigDecimal divide = sumScore.divide(BigDecimal.valueOf(2L), 0, RoundingMode.DOWN);
        return divide.intValue();
    }
}
